package tableaux.backjumping;

import java.util.HashSet;
import java.util.HashMap;
import java.util.Set;
import java.util.Map;

import utils.exception.BackjumpingNoDepSetException;

import entities.Individual;
import entities.concept.Concept;

/**
 * A dependency set has the information: which concept in which node's label
 * depends on which branching
 * 
 * @author j55wu
 * 
 */
public class DependencyImp {

	private static Map<Individual, Map<Concept, Set<Integer>>> deps = new HashMap<Individual, Map<Concept, Set<Integer>>>();

	public static void clearDependencies() {
		deps.clear();
	}

	public static void testMethodFindConceptDep(Concept c) {
		for (Map<Concept, Set<Integer>> v : deps.values()) {
			if (v.containsKey(c)) {
				System.out.println(v.get(c));
			}
		}
	}

	public static void setDep(Individual ind, Concept c, Set<Integer> is) {
		Map<Concept, Set<Integer>> ci;
		if (deps.containsKey(ind)) {
			deps.get(ind).put(c, is);
		} else {
			ci = new HashMap<Concept, Set<Integer>>();
			ci.put(c, is);
			deps.put(ind, ci);
		}
	}

	public static void addDep(Individual ind, Concept c, Set<Integer> is) {
		// if(c.isGuard()){
		// return;
		// }
		Map<Concept, Set<Integer>> ci;
		if (deps.containsKey(ind)) {
			if (deps.get(ind).containsKey(c)) {
				deps.get(ind).get(c).addAll(is);
			} else {
				Set<Integer> nis = new HashSet<Integer>();
				nis.addAll(is);
				deps.get(ind).put(c, nis);
			}
		} else {
			ci = new HashMap<Concept, Set<Integer>>();
			Set<Integer> nis = new HashSet<Integer>();
			nis.addAll(is);
			ci.put(c, nis);
			deps.put(ind, ci);
		}
	}

	public static void addDep(Individual ind, Concept c, Integer i) {
		Map<Concept, Set<Integer>> ci;
		if (deps.containsKey(ind)) {
			if (deps.get(ind).containsKey(c)) {
				deps.get(ind).get(c).add(i);
			} else {
				Set<Integer> is = new HashSet<Integer>();
				is.add(i);
				deps.get(ind).put(c, is);
			}
		} else {
			ci = new HashMap<Concept, Set<Integer>>();
			Set<Integer> is = new HashSet<Integer>();
			is.add(i);
			ci.put(c, is);
			deps.put(ind, ci);
		}
	}

	public static Set<Integer> getDepSetOfConcept(Individual ind, Concept c) {
		if (deps.containsKey(ind)) {
			if (deps.get(ind).containsKey(c)) {
				return deps.get(ind).get(c);
			}
		}
		return new HashSet<Integer>();
	}

	public static boolean dependOnBranch(Individual ind, Concept c, Integer i) {
		if (deps.containsKey(ind) && deps.get(ind).containsKey(c)
				&& deps.get(ind).get(c).contains(i)) {
			return true;
		}
		return false;
	}

	public static Set<Integer> findClashBranch(Individual ind, Concept c1,
			Concept c2) throws BackjumpingNoDepSetException {
		Set<Integer> bs = new HashSet<Integer>();
		Set<Integer> l1 = getDepSetOfConcept(ind, c1);
		Set<Integer> l2 = getDepSetOfConcept(ind, c2);
		if (l1.size() > 0) {
			bs.addAll(l1);
		} else {
			throw new BackjumpingNoDepSetException("No dep set found for " + c1);
		}
		if (l2.size() > 0) {
			bs.addAll(l2);
		} else {
			throw new BackjumpingNoDepSetException("No dep set found for " + c2);
		}
		return bs;
	}

}
